package com.thjk.bdf.common.utils;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;

import okhttp3.ConnectionPool;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * http/https post/get工具类 懒汉模式 double-check
 * 
 * @author hupeng
 * @Time：2018年9月26日 下午7:45:32
 * @version 1.0
 */
public class OkHttpUtil {

	private static final Logger logger = LoggerFactory.getLogger(OkHttpUtil.class);

	private static Gson gson = new Gson();

	private static int maxIdleConnections = 10;
	private static long keepAliveDuration = 5l;
	private static int connTimeout = 20;
	private static int readTimeout = 60;
	private static int writeTimeout = 60;

	private static String contentTypeJSON = "application/json; charset=utf-8";
	private static String contentTypeXml = "application/xml; charset=utf-8";

	private static volatile OkHttpClient okHttpClient = null;

	private static X509TrustManager xtm = null;
	private static SSLContext sslContext = null;
	private static HostnameVerifier DO_NOT_VERIFY = null;
	
	static {
		initX509TrustManager();
		createSSLSocketFactory();
		initHostnameVerifier();
	}

	public static OkHttpClient getInstance() {
		if (okHttpClient == null) {
			synchronized (OkHttpUtil.class) {
				if (okHttpClient == null) {
					okHttpClient = new OkHttpClient().newBuilder()
							.connectionPool(new ConnectionPool(maxIdleConnections, keepAliveDuration, TimeUnit.SECONDS))
							.connectTimeout(connTimeout, TimeUnit.SECONDS).readTimeout(readTimeout, TimeUnit.SECONDS)
							.writeTimeout(writeTimeout, TimeUnit.SECONDS)
							.sslSocketFactory(sslContext.getSocketFactory(), xtm)
							.hostnameVerifier(DO_NOT_VERIFY)
							.build();
				}
			}
		}
		return okHttpClient;
	}

	/**
	 * get
	 * 
	 * @param url
	 *            请求的url
	 * @param queries
	 *            请求的参数，在浏览器？后面的数据，没有可以传null
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static String get(String url, Map<String, String> queries) {

		logger.info("OkHttp request url========" + url);
		logger.info("OkHttp request parameter========" + gson.toJson(queries));

		String responseBody = "";
		StringBuffer sb = new StringBuffer(url);
		if (queries != null && queries.keySet().size() > 0) {
			boolean firstFlag = true;
			Iterator iterator = queries.entrySet().iterator();
			while (iterator.hasNext()) {
				Map.Entry entry = (Map.Entry<String, String>) iterator.next();
				if (firstFlag) {
					sb.append("?" + entry.getKey() + "=" + entry.getValue());
					firstFlag = false;
				} else {
					sb.append("&" + entry.getKey() + "=" + entry.getValue());
				}
			}
		}
		Request request = new Request.Builder().url(sb.toString()).build();
		Response response = null;
		try {
			OkHttpClient okHttpClient = getInstance();
			response = okHttpClient.newCall(request).execute();
			if (response.isSuccessful()) {
				return response.body().string();
			}
		} catch (Exception e) {
			logger.error("okhttp3 put error >> ex = {}", ExceptionUtils.getStackTrace(e));
		} finally {
			if (response != null) {
				response.close();
			}
		}
		logger.info("OkHttp response========" + responseBody);
		return responseBody;
	}

	/**
	 * post
	 *
	 * @param url
	 *            请求的url
	 * @param params
	 *            post form 提交的参数
	 * @return
	 */
	public static String post(String url, Map<String, String> params) {

		logger.info("OkHttp request url========" + url);
		logger.info("OkHttp request parameter========" + gson.toJson(params));

		String responseBody = "";
		FormBody.Builder builder = new FormBody.Builder();
		// 添加参数
		if (params != null && params.keySet().size() > 0) {
			for (String key : params.keySet()) {
				builder.add(key, params.get(key));
			}
		}
		Request request = new Request.Builder().url(url).post(builder.build()).build();
		Response response = null;
		try {
			OkHttpClient okHttpClient = getInstance();
			response = okHttpClient.newCall(request).execute();
			if (response.isSuccessful()) {
				return response.body().string();
			}
		} catch (Exception e) {
			logger.error("okhttp3 post error >> ex = {}", ExceptionUtils.getStackTrace(e));
		} finally {
			if (response != null) {
				response.close();
			}
		}
		logger.info("OkHttp response========" + responseBody);
		return responseBody;
	}

	/**
	 * get
	 * 
	 * @param url
	 *            请求的url
	 * @param queries
	 *            请求的参数，在浏览器？后面的数据，没有可以传null
	 * @param headParam
	 *            请求的报文头
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static String getForHeader(String url, Map<String, String> queries, Map<String, Object> headParam) {

		logger.info("OkHttp request url========" + url);
		logger.info("OkHttp request parameter========" + gson.toJson(queries));
		logger.info("OkHttp request headParam========" + gson.toJson(headParam));

		String responseBody = "";
		StringBuffer sb = new StringBuffer(url);
		if (queries != null && queries.keySet().size() > 0) {
			boolean firstFlag = true;
			Iterator iterator = queries.entrySet().iterator();
			while (iterator.hasNext()) {
				Map.Entry entry = (Map.Entry<String, String>) iterator.next();
				if (firstFlag) {
					sb.append("?" + entry.getKey() + "=" + entry.getValue());
					firstFlag = false;
				} else {
					sb.append("&" + entry.getKey() + "=" + entry.getValue());
				}
			}
		}
		//Request request = new Request.Builder().addHeader("key", "value").url(sb.toString()).build();
		
		// 设置header
		Request.Builder requestBuilder = new Request.Builder();
		if (!MapUtils.isEmpty(headParam)) {
			for (Map.Entry<String, Object> entry : headParam.entrySet()) {
				requestBuilder.addHeader(entry.getKey(), entry.getValue().toString());
			}
		}
		Request request = requestBuilder.url(sb.toString()).build();
		
		Response response = null;
		try {
			OkHttpClient okHttpClient = getInstance();
			response = okHttpClient.newCall(request).execute();
			if (response.isSuccessful()) {
				return response.body().string();
			}
		} catch (Exception e) {
			logger.error("okhttp3 put error >> ex = {}", ExceptionUtils.getStackTrace(e));
		} finally {
			if (response != null) {
				response.close();
			}
		}
		logger.info("OkHttp response========" + responseBody);
		return responseBody;
	}

	/**
	 * Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"} 参数一：请求Url
	 * 参数二：请求的JSON 参数三：请求回调
	 */
	public static String postJsonParams(String url, String jsonParams) {

		logger.info("OkHttp request url========" + url);
		logger.info("OkHttp request parameter========" + jsonParams);

		String responseBody = "";
		RequestBody requestBody = RequestBody.create(MediaType.parse(contentTypeJSON), jsonParams);
		Request request = new Request.Builder().url(url).post(requestBody).build();
		Response response = null;
		try {
			OkHttpClient okHttpClient = getInstance();
			response = okHttpClient.newCall(request).execute();
			if (response.isSuccessful()) {
				return response.body().string();
			}
		} catch (Exception e) {
			logger.error("okhttp3 post error >> ex = {}", ExceptionUtils.getStackTrace(e));
		} finally {
			if (response != null) {
				response.close();
			}
		}
		logger.info("OkHttp response========" + responseBody);
		return responseBody;
	}

	/**
	 * 加header
	 * 
	 * @param url
	 * @param jsonParams
	 * @param headParam
	 * @return
	 */
	public static String postJsonParams(String url, String jsonParams, Map<String, Object> headParam) {

		logger.info("OkHttp request url========" + url);
		logger.info("OkHttp request parameter========" + jsonParams);
		logger.info("OkHttp request headParam========" + headParam);

		String responseBody = "";

		RequestBody requestBody = RequestBody.create(MediaType.parse(contentTypeJSON), jsonParams);
		Request.Builder requestBuilder = new Request.Builder();

		// 设置header
		if (!MapUtils.isEmpty(headParam)) {
			for (Map.Entry<String, Object> entry : headParam.entrySet()) {
				requestBuilder.addHeader(entry.getKey(), gson.toJson(entry.getValue()));
			}
		}

		Request request = requestBuilder.url(url).post(requestBody).build();
		Response response = null;
		try {
			OkHttpClient okHttpClient = getInstance();
			response = okHttpClient.newCall(request).execute();
			if (response.isSuccessful()) {
				return response.body().string();
			}
		} catch (Exception e) {
			logger.error("okhttp3 post error >> ex = {}", ExceptionUtils.getStackTrace(e));
		} finally {
			if (response != null) {
				response.close();
			}
		}
		logger.info("OkHttp response========" + responseBody);
		return responseBody;
	}
	
	/**
	 * Post请求发送xml数据.... 参数一：请求Url 参数二：请求的xmlString 参数三：请求回调
	 */
	public static String postXmlParams(String url, String xml) {

		logger.info("OkHttp request url========" + url);
		logger.info("OkHttp request parameter========" + xml);

		String responseBody = "";
		RequestBody requestBody = RequestBody.create(MediaType.parse(contentTypeXml), xml);
		Request request = new Request.Builder().url(url).post(requestBody).build();
		Response response = null;
		try {
			OkHttpClient okHttpClient = getInstance();
			response = okHttpClient.newCall(request).execute();
			if (response.isSuccessful()) {
				return response.body().string();
			}
		} catch (Exception e) {
			logger.error("okhttp3 post error >> ex = {}", ExceptionUtils.getStackTrace(e));
		} finally {
			if (response != null) {
				response.close();
			}
		}
		logger.info("OkHttp response========" + responseBody);
		return responseBody;
	}

	private static SSLSocketFactory createSSLSocketFactory() {
		try {
			sslContext = SSLContext.getInstance("SSL");

			sslContext.init(null, new TrustManager[] { xtm }, new SecureRandom());

		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		}
		return sslContext.getSocketFactory();
	}

	private static X509TrustManager initX509TrustManager() {
		xtm = new X509TrustManager() {

			@Override
			public X509Certificate[] getAcceptedIssuers() {
				X509Certificate[] x509Certificates = new X509Certificate[0];
				return x509Certificates;
			}

			@Override
			public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
			}

			@Override
			public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
			}
		};

		return xtm;
	}

	/**
	 * 设置忽略认证
	 * 
	 * @return
	 */
	private static HostnameVerifier initHostnameVerifier() {
		DO_NOT_VERIFY = new HostnameVerifier() {

			@Override
			public boolean verify(String hostname, SSLSession session) {
				return true;
			}
		};
		return DO_NOT_VERIFY;
	}
	
	/*public static void main(String args[]) throws IOException {
    	TreeMap<String, Object> map = new TreeMap<String, Object>();
		map.put("TranDate","20180921100500");
		map.put("SeriNo","1000000000010001");
		map.put("SysCode","600004");
		map.put("ChanId","01");
		map.put("ChanSystem","01");
		map.put("Product","600004");
		map.put("OrgCode","00010001");
		map.put("TranCode","LN6001");
		
		map.put("SignatureDataBase64","K/Pi6FY9r3KJd8weu2FXakoLqM1Sspoq0qMcNcpp0SN7m5wR6m8qR0/p0IPQNMozceQSHFCLRIcK\r\nBW+bIgKfocimEZBYDMerIDwoGUyDj7wSLDwCKVNybfK3If8Vq096jHDBwIld46uybSwWFEYqBPVX\r\nEQWIRLhtvOHF9+vnil8=\r\n");
		map.put("Sign","BAHrSXfsJX8b0/j3J63Rtwl6hfJDNbHJRGQ3VTflrbzv0JbhuIE14pHSh1rw/BCje7i+BbS14evb\r\npyDy29McoCC/nuwngqOWdNn5zt7TNfi26vs3x9giBCC3TlDvibQ0vqRHluGRNcj8ZVkFoVUfdIqC\r\nUQTvxaecpaZX/V7MTyA=\r\n");
		JSONObject dataJson = new JSONObject(map);
        String result = OkHttpUtil.postJsonParams("https://58.247.5.139:9997/out-front/LN6001.do", dataJson.toString());
        System.out.println(result);
    }*/
}
